<?php

namespace App\Trip\Wechat\MiniApp;


use App\Trip\Wechat\Traits\ApplicationTrait;
use App\Trip\Wechat\WxBizDataCrypt;
use EasyWeChat\Kernel\Contracts\Config as ConfigInterface;
use Exception;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;

class Application extends \EasyWeChat\MiniApp\Application
{
    use ApplicationTrait;

    public function __construct(ConfigInterface|array $config)
    {
        parent::__construct($config);
    }

    /**
     * @throws Exception
     */
    public function getUserData(string $code, string $iv, string $encrypted): array
    {

        $res     = $this->code2Session($code);
        $account = $this->getAccount();
        $crypt   = new WxBizDataCrypt($account->getAppId(), $res['session_key']);
        $code    = $crypt->decryptData($encrypted, $iv);
        if (0 != $code) {
            throw new Exception($crypt->getErrorMsg());
        }
        $contents = $crypt->getDecryptData();
        $result   = json_decode($contents, true);

        $ret = [
            'openid'    => $res['openid'],
            'unionid'   => $res['unionid'],
            'watermark' => $result['watermark'],
        ];

        if (isset($result['nickName'])) {
            $ret['nickName']  = $result['nickName'];
            $ret['avatarUrl'] = $result['avatarUrl'];
        } else if (isset($result['phoneNumber'])) {
            $ret['phoneNumber']     = $result['phoneNumber'];
            $ret['purePhoneNumber'] = $result['purePhoneNumber'];
        } else {
            throw new Exception("getUserData error");
        }
        return $ret;
    }

    /**
     * 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。
     * @throws TransportExceptionInterface
     * @throws Exception
     * @throws DecodingExceptionInterface
     */
    public function code2Session(string $code): array
    {
        $account  = $this->getAccount();
        $api      = $this->getClient();
        $response = $api->get("/sns/jscode2session", [
            "query" => [
                "appid"      => $account->getAppId(),
                "secret"     => $account->getSecret(),
                "js_code"    => $code,
                "grant_type" => "authorization_code",
            ],
        ])->toArray();


        return [
            "openid"      => $response["openid"],
            "session_key" => $response["session_key"],
            "unionid"     => $response["unionid"],
        ];
    }


}